﻿// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
//
// 本项目主要遵循 MIT 许可证和 Apache 许可证（版本 2.0）进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
//
// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动！任何基于本项目二次开发而产生的一切法律纠纷和责任，我们不承担任何责任！

using Aop.Api.Domain;
using Azure.Core;
using MQTTnet;
using MQTTnet.Packets;
using MQTTnet.Protocol;
using Newtonsoft.Json;
using SKIT.FlurlHttpClient.Wechat.TenpayV3.Models;
using SL.NET.Core.Service;




//using MQTTnet.Channel;
//using MQTTnet.Extensions.ManagedClient;
//using MQTTnet.Protocol;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using WCS.Application.Service.Plc;
using System.Text.Json;
using NewLife;
using JsonSerializer = Newtonsoft.Json.JsonSerializer;
using static SKIT.FlurlHttpClient.Wechat.Api.Models.ComponentTCBBatchCreateContainerServiceVersionResponse.Types;
using MQTTnet.Formatter;
using Tea.Utils;

namespace MyDemo.Application.Service.Plc;
/// <summary>
/// MQ客户端
/// </summary>
[ApiDescriptionSettings(groups: ApplicationConst.GroupName, Order = 11)]
[AllowAnonymous]
public class MqttClientService : IDynamicApiController ,ITransient
{
    private readonly IMqttClient _mqttClient;
    private readonly MqttClientOptions _clientOptions;
    private bool _isConnected;
    private readonly SysCacheService _sysCacheService;


    public MqttClientService(SysCacheService sysCacheService)
    {
        // 构建 MQTT 客户端选项
        var optionsBuilder = new MqttClientOptionsBuilder()
           .WithTcpServer("localhost", 1888)
           .WithProtocolVersion(MqttProtocolVersion.V311)
           //.WithCredentials("admin", "admin")
           .WithClientId("WarehousId")
           .WithCleanSession()
           .WithTlsOptions(new MqttClientTlsOptions
           {
               UseTls = false
           });

        _clientOptions = optionsBuilder.Build();
        // 创建 MQTT 客户端
        _mqttClient = new MqttClientFactory().CreateMqttClient();

        //订阅消息接收事件
        //_mqttClient.ApplicationMessageReceivedAsync += HandleReceivedMessage;
        _isConnected = false;
        _sysCacheService = sysCacheService;
        // Task.Run(async () => await _mqttClient.ConnectAsync(_clientOptions));

    }

    #region 读MQtt


    [ApiDescriptionSettings(Name = "MqttClientServiceStart"), HttpPost]
    public async Task<List<Tuple<object, object>>> MqttServerReader(string Topic = "c", string key = "Wm210")
    {
        var mqttService = new MqttClientService(_sysCacheService);
        var cancellationTokenSource = new CancellationTokenSource();
        var resultList = new List<Tuple<object, object>>();
        //多个AGV小车
        for (int i = 1; i <= 6; i++)
        {
            var modifiedTopic = ModifyTopic(Topic, i);
            await mqttService._mqttClient_SubscribeAsync(cancellationTokenSource.Token, modifiedTopic, key);

            resultList.Add(new Tuple<object, object>(new { Topic = modifiedTopic, Key = key },new { Index = i }));
        }

        // 连接到 MQTT 服务器  
        var connectResult = await _mqttClient.ConnectAsync(_clientOptions, cancellationTokenSource.Token);
        Console.WriteLine("Press any key to stop the service...");
        Console.ReadKey();

        // 关闭  
        await mqttService.StopAsync(cancellationTokenSource.Token);

        return resultList;
    }
    /// <summary>
    /// 获取redsi 节点和k
    /// </summary>
    /// <param name="topic"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    [ApiDescriptionSettings(Name = "RedisGet"), HttpPost]
    public Task<string> RedisGet(string topic, string value = "")
    {
        var topicjson = "";
        var c = _sysCacheService.GetKeyList();
        if (_sysCacheService.ExistKey(topic))
        {
            topicjson = _sysCacheService.Get<string>(topic);
            if (topicjson == null)
            {
                //从redis抓紧获取
                throw Oops.Oh($"Redis为存放ksy为{topic}的，请稍后再试");
            }
        }
        else
        {
            throw Oops.Oh($"Redis无此{topic}，请稍后再试");

        }
        string jsonText = "{\"ClassName\":\"Science\",\"Final\":true,\"Semester\":\"2019-01-01\",\"Students\":[{\"Name\":\"John\",\"Grade\":94.3},{\"Name\":\"James\",\"Grade\":81.0},{\"Name\":\"Julia\",\"Grade\":91.9},{\"Name\":\"Jessica\",\"Grade\":72.4},{\"Name\":\"Johnathan\"}],\"Teacher'sName\":\"Jane\"}";
        JsonDocument doc = JsonDocument.Parse(topicjson);
        JsonElement root = doc.RootElement;

        // 将 root 转为动态对象
        dynamic dynamicObject = JsonConvert.DeserializeObject<dynamic>(root.GetRawText());

        if (value != "")
        {
            Console.WriteLine($"topic from Redis: {topic},字段{value}:{dynamicObject[value]}");
            return Task.FromResult(dynamicObject[value]?.ToString());
        }
        else
        {
            Console.WriteLine($"topic from Redis: {topic},{value}:");
            return Task.FromResult(dynamicObject.ToString());
        }
    }
    /// <summary>
    /// 订阅多个主题
    /// </summary>
    /// <param name="cancellationToken"></param>
    /// <returns></returns>
    private async Task _mqttClient_SubscribeAsync(CancellationToken cancellationToken, string topic, string code)
    {

        try
        {
            //连接到 MQTT 服务器
            if (!_isConnected)
            {
                var connectResult = await _mqttClient.ConnectAsync(_clientOptions, cancellationToken);
                if (connectResult.ResultCode == MqttClientConnectResultCode.Success)
                {
                    _isConnected = true;
                    Console.WriteLine("Connected to MQTT server successfully.");
                }
                else
                {
                    Console.WriteLine($"Failed to connect to MQTT server. Result code: {connectResult.ResultCode}");
                }
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred while connecting to MQTT server: {ex.Message}");
        }
        string[] parts = topic.Split(',');
        var topicsToSubscribe = new List<MqttTopicFilter>();
        //if (parts.Length>1)
        //{
        // 构建 MqttClientSubscribeOptions 对象  
        // 定义要订阅的主题  
        var topicFilter = new MqttTopicFilterBuilder().WithTopic(topic.Trim()).Build();
        // 创建单个订阅选项  
        var subscribeOption = new MqttClientSubscribeOptionsBuilder()
          .WithTopicFilter(topicFilter)
          .Build();
        // 订阅单个主题  
        var subscribeResult = await _mqttClient.SubscribeAsync(subscribeOption);

        if (subscribeResult.Items.Any(item => item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS0 ||
                                              item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS1 ||
                                              item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS2))
        {
            Console.WriteLine("Successfully subscribed to the topic.");
        }
        else
        {
            Console.WriteLine("Failed to subscribe to the topic.");
        }

        // 订阅消息接收事件  
        _mqttClient.ApplicationMessageReceivedAsync += _mqttClient_ApplicationMessageReceivedAsync;

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
        #region 多个

        // 断开连接  
        //await _mqttClient.DisconnectAsync();
        //    //多个主题订阅
        //    foreach (string part in parts)
        //    {
        //        if (!string.IsNullOrEmpty(part))
        //        {
        //            topicsToSubscribe.Add(new MqttTopicFilterBuilder().WithTopic(part.Trim()).Build());
        //        }
        //    }

        //    //订阅多个主题

        //    var subscribeOptionsBuilder = new MqttClientSubscribeOptionsBuilder();
        //    foreach (var item in topicsToSubscribe)
        //    {
        //        //多个主题订阅
        //        subscribeOptionsBuilder = subscribeOptionsBuilder.WithTopicFilter(item).Build();
        //        var subscribeOptions = subscribeOptionsBuilder.Build();

        //    }
        //    // 订阅多个主题
        //    subscribeResult = await _mqttClient.SubscribeAsync(subscribeOptions);
        //    foreach (var itemtopic in subscribeResult.Items)
        //    {
        //        var topicFilters = itemtopic.TopicFilter;
        //        var topisc = topicFilters.Topic;
        //        var resultCode = itemtopic.ResultCode;
        //        Console.WriteLine($"Topic: {topisc}, Subscription Result Code: {resultCode}");
        //    }
        //}

        //单个
        //// 构建 MqttClientSubscribeOptions 对象
        //// 定义要订阅的主题
        //var topicFilter = new MqttTopicFilterBuilder().WithTopic(parts.ToString()).Build();
        //// 创建单个订阅选项
        //var _mqtt = new MqttClientSubscribeOptionsBuilder()
        //   .WithTopicFilter(topicFilter)
        //   .Build();
        //// 订阅单个主题
        //subscribeResult = await _mqttClient.SubscribeAsync(subscribe OptionWithTopic);
        #endregion

        if (subscribeResult.Items.Count > 0)
        {
            Console.WriteLine("Successfully subscribed to all topics.");
        }
        else
        {
            Console.WriteLine("cFailed to subscribe to some topics.");
        }

    }



    private Task _mqttClient_ApplicationMessageReceivedAsync(MqttApplicationMessageReceivedEventArgs arg)
    {
        Console.WriteLine($"收到服务iotid{arg.ClientId},主题是Topic={arg.ApplicationMessage.Topic},信息{Encoding.UTF8.GetString(arg.ApplicationMessage.Payload)},qos等级{arg.ApplicationMessage.QualityOfServiceLevel}");
        //throw new NotImplementedException();
        string topic = arg.ApplicationMessage.Topic;
        string payload = System.Text.Encoding.UTF8.GetString(arg.ApplicationMessage.Payload);
        // 将消息数据存储到 Redis
        string[] parts = topic.Split('/');
        if (parts.Length == 3)
        {

            // Dictionary<string, object> dataDict = new JsonConvert.DeserializeObject<Dictionary<string, object>>(payload);
            //添加哈希信息
            _sysCacheService.Set(parts[1], payload.ToString());
            // RedisSingleton.Instance.Database.StringSet(parts[1], payload);
        }
        Console.WriteLine($"Received message on topic: {topic}, Payload: {payload}. Stored in Redis.");
        switch (topic)
        {
            case "devices/水表/telemetry":
                Console.WriteLine($"Received message on topic1: {payload}. Performing topic1 specific logic...");
                // 这里添加 topic1 对应的逻辑处理代码    
                break;
            case "devices/电表/telemetry":
                Console.WriteLine($"Received message on topic2: {payload}. Performing topic2 specific logic...");
                //Dictionary<string, object> dataDict = JsonConvert.DeserializeObject<Dictionary<string, object>>(payload);
                //if (dataDict.TryGetValue("电流", out object dianl))
                //{
                //    return Task.FromResult<object>(new { kay = dianl });
                //}
                break;
            case "devices/WarehouseAGV02/telemetry":
                Console.WriteLine($"Received message on topic3: {payload}. Performing topic3 specific logic...");
                // 这里添加 topic3 对应的逻辑处理代码
                break;
            default:
                Console.WriteLine($"Received message on an unknown topic: {topic}, Payload: {payload}");
                break;
                //return Task.CompletedTask;
        }

        return Task.CompletedTask;
    }
    #endregion

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        try
        {
            if (_mqttClient.IsConnected)
            {
                // 创建断开连接选项
                var disconnectOptions = new MqttClientDisconnectOptions
                {
                    Reason = (MqttClientDisconnectOptionsReason)MqttClientDisconnectReason.NormalDisconnection,
                    ReasonString = "Service is being stopped.停止"
                };

                await _mqttClient.DisconnectAsync(disconnectOptions, cancellationToken);
                Console.WriteLine("Disconnected from MQTT server.");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error while disconnecting: {ex.Message}");
        }
    }


    /// <summary>
    /// 写Mqtt发布消息给指定的主题+信息
    /// </summary>
    /// <param name="topic">对应的话题</param>
    /// <param name="messageObject">更新的信息</param>
    /// <returns></returns>

    [ApiDescriptionSettings(Name = "PublishMessage"), HttpPost]
    public async Task<MqttResponseResult> PublishMessage(string topic = "devices/水表/telemetry", string messageObject = "")
    {
        try
        {
            var mqttService = new MqttClientService(_sysCacheService);
            _isConnected = false;
            var cancellationTokenSource = new CancellationTokenSource();

            // 如果未连接，则尝试连接到 MQTT 服务器

            if (!_isConnected)
            {

                var connectResult = await _mqttClient.ConnectAsync(_clientOptions, cancellationTokenSource.Token);
                if (connectResult.ResultCode != MqttClientConnectResultCode.Success)
                {
                    Console.WriteLine($"Failed to connect to MQTT server. Result code: {connectResult.ResultCode}");

                    return MqttResponseResult.Failure("MQTT连接失败");
                }
                _isConnected = true;
                Console.WriteLine("Connected to MQTT server successfully.");
            }

            // 如果 messageObject 为 null，则使用空字符串
            messageObject = messageObject ?? string.Empty;
            // 将对象序列化为 JSON 字符串
            string jsonMessage = JsonConvert.SerializeObject(messageObject);
            // 创建 MQTT 应用消息
            var message = new MqttApplicationMessageBuilder()
               .WithTopic(topic)
               .WithPayload(Encoding.UTF8.GetBytes(jsonMessage))
               .WithQualityOfServiceLevel(MqttQualityOfServiceLevel.AtLeastOnce)
               .WithRetainFlag(true)
               .Build();

            // 发布消息
            var publishResult = await _mqttClient.PublishAsync(message);
            if (publishResult.ReasonCode != MqttClientPublishReasonCode.Success)
            {
                Console.WriteLine($"Failed to publish message. Reason code: {publishResult.ReasonCode}");
                return MqttResponseResult.Failure($"MQTT发送失败code:{publishResult.ReasonCode}");

            }
            Console.WriteLine("Message published successfully.");
            await mqttService.StopAsync(cancellationTokenSource.Token);

            return MqttResponseResult.Success(new { Data = publishResult.IsSuccess }, "发送操作成功"); ;
        }
        catch (Exception ex)
        {
            // 捕获并处理异常
            Console.WriteLine($"An error occurred while publishing message: {ex.Message}");
            return MqttResponseResult.Failure($"MQTT发送异常code:{ex.Message}");
        }
    }



    #region 写mqtt
    public async Task MqttClient_WriteAsync(CancellationToken cancellationToken, string topic, string code)
    {

        try
        {
            //连接到 MQTT 服务器
            if (!_isConnected)
            {
                var connectResult = await _mqttClient.ConnectAsync(_clientOptions, cancellationToken);
                if (connectResult.ResultCode == MqttClientConnectResultCode.Success)
                {
                    _isConnected = true;
                    Console.WriteLine("Connected to MQTT server successfully.");
                }
                else
                {
                    Console.WriteLine($"Failed to connect to MQTT server. Result code: {connectResult.ResultCode}");
                }
            }

        }
        catch (Exception ex)
        {
            Console.WriteLine($"An error occurred while connecting to MQTT server: {ex.Message}");
        }


        string[] parts = topic.Split(',');
        var topicsToSubscribe = new List<MqttTopicFilter>();
        //if (parts.Length>1)
        //{
        // 构建 MqttClientSubscribeOptions 对象  
        // 定义要订阅的主题  
        var topicFilter = new MqttTopicFilterBuilder().WithTopic(topic.Trim()).Build();
        // 创建单个订阅选项  
        var subscribeOption = new MqttClientSubscribeOptionsBuilder()
          .WithTopicFilter(topicFilter)
          .Build();
        // 订阅单个主题  
        var subscribeResult = await _mqttClient.SubscribeAsync(subscribeOption);

        if (subscribeResult.Items.Any(item => item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS0 ||
                                              item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS1 ||
                                              item.ResultCode == MqttClientSubscribeResultCode.GrantedQoS2))
        {
            Console.WriteLine("Successfully subscribed to the topic.");
        }
        else
        {
            Console.WriteLine("Failed to subscribe to the topic.");
        }

        // 订阅消息接收事件  
        _mqttClient.ApplicationMessageReceivedAsync += _mqttClient_ApplicationMessageReceivedAsync;

        Console.WriteLine("Press any key to exit...");
        Console.ReadKey();
        #region 多个

        // 断开连接  
        //await _mqttClient.DisconnectAsync();
        //    //多个主题订阅
        //    foreach (string part in parts)
        //    {
        //        if (!string.IsNullOrEmpty(part))
        //        {
        //            topicsToSubscribe.Add(new MqttTopicFilterBuilder().WithTopic(part.Trim()).Build());
        //        }
        //    }

        //    //订阅多个主题

        //    var subscribeOptionsBuilder = new MqttClientSubscribeOptionsBuilder();
        //    foreach (var item in topicsToSubscribe)
        //    {
        //        //多个主题订阅
        //        subscribeOptionsBuilder = subscribeOptionsBuilder.WithTopicFilter(item).Build();
        //        var subscribeOptions = subscribeOptionsBuilder.Build();

        //    }
        //    // 订阅多个主题
        //    subscribeResult = await _mqttClient.SubscribeAsync(subscribeOptions);
        //    foreach (var itemtopic in subscribeResult.Items)
        //    {
        //        var topicFilters = itemtopic.TopicFilter;
        //        var topisc = topicFilters.Topic;
        //        var resultCode = itemtopic.ResultCode;
        //        Console.WriteLine($"Topic: {topisc}, Subscription Result Code: {resultCode}");
        //    }
        //}

        //单个
        //// 构建 MqttClientSubscribeOptions 对象
        //// 定义要订阅的主题
        //var topicFilter = new MqttTopicFilterBuilder().WithTopic(parts.ToString()).Build();
        //// 创建单个订阅选项
        //var _mqtt = new MqttClientSubscribeOptionsBuilder()
        //   .WithTopicFilter(topicFilter)
        //   .Build();
        //// 订阅单个主题
        //subscribeResult = await _mqttClient.SubscribeAsync(subscribe OptionWithTopic);
        #endregion

        if (subscribeResult.Items.Count > 0)
        {
            Console.WriteLine("Successfully subscribed to all topics.");
        }
        else
        {
            Console.WriteLine("cFailed to subscribe to some topics.");
        }

    }

    private string ModifyTopic(string topic,int i)
    {
        // 检查 topic 是否符合预期格式  
        var parts = topic.Split('/');
        if (parts.Length == 4 && int.TryParse(parts[2], out int middleValue))
        {
            // 替换中间值的最后一位为 'i'  
            var modifiedMiddleValue = middleValue.ToString().Substring(0, middleValue.ToString().Length - 1) + i;
            parts[2] = modifiedMiddleValue;
            return string.Join("/", parts);
        }
        return topic; // 如果格式不符合，返回原始 topic  
    }



    #endregion

}





/// <summary>  
/// 统一的反馈结果类  
/// </summary>  
public class MqttResponseResult
{
    /// <summary>  
    /// 是否成功  
    /// </summary>  
    public bool IsSuccess { get; set; }

    /// <summary>  
    /// 返回的消息  
    /// </summary>  
    public string Message { get; set; }

    /// <summary>  
    /// 返回的数据  
    /// </summary>  
    public object Data { get; set; }

    /// <summary>  
    /// 构造成功的反馈结果  
    /// </summary>  
    /// <param name="data">返回的数据</param>  
    /// <param name="message">返回的消息</param>  
    /// <returns>MqttResponseResult</returns>  
    public static MqttResponseResult Success(object data = null, string message = "操作成功")
    {
        return new MqttResponseResult
        {
            IsSuccess = true,
            Message = message,
            Data = data
        };
    }

    /// <summary>  
    /// 构造失败的反馈结果  
    /// </summary>  
    /// <param name="message">错误消息</param>  
    /// <returns>MqttResponseResult</returns>  
    public static MqttResponseResult Failure(string message = "操作失败")
    {
        return new MqttResponseResult
        {
            IsSuccess = false,
            Message = message,
            Data = null
        };
    }
}
